﻿namespace Wolfpack.Contrib.Checks.Uptime
{
    using System;
    using System.Diagnostics;
    using Wolfpack.Core;
    using Wolfpack.Core.Interfaces;
    using Wolfpack.Core.Interfaces.Entities;

    //// Agent:  Event Log - Extend to Support Detect If No Reboot in X hours as failure
    public class UptimeAlarmConfig : PluginConfigBase
    {
        public string HoursThreshold { get; set; }
    }

    /// <summary>
    /// The Plugin.
    /// </summary>
    public class UptimeAlarm : IHealthCheckPlugin
    {
        public const float SECONDSINHOUR = 3600;

        private readonly UptimeAlarmConfig myConfig;

        public UptimeAlarm(UptimeAlarmConfig config)
        {
            this.myConfig = config;
        }

        public Status Status { get; set; }

        public PluginDescriptor Identity
        {
            get
            {
                return new PluginDescriptor
                {
                    Description = "System Uptime Alarm",
                    Name = this.myConfig.FriendlyId,

                    // The TypeId is important - it needs to be different for
                    // each health check as this allows us to positively identify
                    // every health check. Use the VS Tools/Create GUID tool to
                    // generate a new one.
                    TypeId = new Guid("047CDD0B-0E17-43e2-9B83-0DA501DB70EF")
                };
            }
        }

        /// <summary>
        /// Performs a one-time initialization.
        /// </summary>
        public void Initialise()
        {
        }

        /// <summary>
        /// Checks the current registry value against the last known value.  If no known value exists or
        /// if the value has changed, send a message.
        /// </summary>
        public void Execute()
        {
            Logger.Debug("{0} is checking to see if uptime is greater than {1} hours.", this.myConfig.FriendlyId, this.myConfig.HoursThreshold);

            try
            {
                PerformanceCounter uptime = new PerformanceCounter("System", "System Up Time");

                // The first read operation using the new properties returns 0.0.
                // So call NextValue() twice.
                uptime.NextValue();

                float secondsUp = uptime.NextValue();
                float hoursUp = secondsUp / SECONDSINHOUR;
                float hoursThreshold = float.Parse(this.myConfig.HoursThreshold);

                Logger.Debug("{0}, uptime is {1} hours, threshold is {2} hours.", this.myConfig.FriendlyId, hoursUp.ToString(), hoursThreshold.ToString());

                if (hoursUp > hoursThreshold)
                {
                    Logger.Debug("Alarm Condition met! Publishing check {0}.", this.myConfig.FriendlyId);
                    Messenger.Publish(
                        new HealthCheckData
                        {
                            Identity = this.Identity,
                            Result = false,
                            Info = "System uptime of " + hoursUp.ToString() + " is greater than the defined threshold of " + this.myConfig.HoursThreshold,
                            Tags = hoursUp.ToString()
                        });
                }
            }
            catch (Exception e)
            {
                Logger.Error("Error while calculating uptime. {0}", e.InnerException.ToString());
            }

            Logger.Debug("{0} is done checking uptime.", this.myConfig.FriendlyId);
        }
    }
}